#include <string.h>
static unsigned char Chr2Base(char);
static char  Base2Chr(unsigned char);

/* ==========================================
功能：Base64编码
输入：iLen-aSrc的长度，
	  aSrc-待编码文本
输出：aDest-Base64码，
	  缓冲区必须至少是：(iLen/3 + 1) * 4
返回：aDest的实际长度
	  输出Base64编码的实际长度计算如下：
	  (iLen / 3 + ((iLen % 3) ? 1 : 0)) * 4
*/
int Base64Encode(char *const aDest, const unsigned char* aSrc, int iLen)
{
	char	*p = aDest;
    int		i;
    unsigned char t=0;

    for (i = 0; i < iLen; i++)
    {
    	switch (i % 3)
        {
			case 0 :
				*p++ = Base2Chr(*aSrc >> 2);
				t = (*aSrc++ << 4) & 0x3F;
				break;
			case 1 :
				*p++ = Base2Chr(t | (*aSrc >> 4));
				t = (*aSrc++ << 2) & 0x3F;
				break;
			case 2 :
				*p++ = Base2Chr(t | (*aSrc >> 6));
				*p++ = Base2Chr(*aSrc++);
				break;
        }
    }
    if (iLen % 3 != 0)
    {
    	*p++ = Base2Chr(t);
        if (iLen % 3 == 1)
        	*p++ = '=';
        *p++ = '=';
    }
    *p = 0;					/*aDest is an ASCIIZ string*/
	return (p - aDest);		/*exclude the end of zero*/
}

/* =========================================================
功能：Base64解码
输入：aSrc-待解码文本
输出：aDest-解码后的文本，缓冲区必须至少是aSrc长度的0.75倍
返回：aDest的实际长度
*/
int Base64Decode(unsigned char *const aDest, const char *aSrc)
{
	unsigned char * p = aDest;
    int	i, n = strlen(aSrc);
    unsigned char   c=0, t=0;

    for (i = 0; i < n; i++)
    {
    	if (*aSrc == '=')
		{
        	break;
		}
        do
		{
        	if (*aSrc)
			{
		       	c = Chr2Base(*aSrc++);
			}
            else
			{
            	c = 65;       /*  字符串结束 */
			}
        } while (c == 64);  /*  跳过无效字符，如回车等 */
        if (c == 65)
		{
        	break;
		}
        switch (i % 4)
        {
			case 0 :
				t = c << 2;
				break;
			case 1 :
				*p++ = (unsigned char)(t | (c >> 4));
				t = (unsigned char)(c << 4);
				break;
			case 2 :
				*p++ = (unsigned char)(t | (c >> 2));
				t = (unsigned char)(c << 6);
				break;
			case 3 :
				*p++ = (unsigned char)(t | c);
				break;
        }
    }
	return (p - aDest);
}

static char  Base2Chr(unsigned char n)
{
	n &= 0x3F;
	if (n < 26)
    	return (char)(n + 'A');
    else if (n < 52)
    	return (char)(n - 26 + 'a');
    else if (n < 62)
    	return (char)(n - 52 + '0');
    else if (n == 62)
    	return '+';
    else
    	return '/';
}

/* ==========================================
*/
static unsigned char Chr2Base(char c)
{
	if (c >= 'A' && c <= 'Z')
    	return (unsigned char)(c - 'A');
    else if (c >= 'a' && c <= 'z')
    	return (unsigned char)(c - 'a' + 26);
    else if (c >= '0' && c <= '9')
    	return (unsigned char)(c - '0' + 52);
    else if (c == '+')
    	return 62;
    else if (c == '/')
    	return 63;
    else
        return 64;  /*无效字符*/
}


/*************************************************
for test
**************************************************
main(int argc, char **argv)
{

	int		len = 0, iRet = 0;
	char	oBuf[64];
	const	char iBuf[11];
	char	tmpBuf[64];

	if(argc < 2)
	{
		return(-1);
	}

	strcpy(iBuf, argv[1]);

	len = (strlen(iBuf)/3 + (strlen(iBuf) % 3 ? 1 : 0)) * 4;
	iRet = Base64Encode(oBuf, (unsigned char *)iBuf, strlen(iBuf));
	printf("Encode is [%s][%d][%d]\n", oBuf, iRet, len);
	iRet = Base64Decode((unsigned char *)tmpBuf, oBuf);
	printf("Decode is [%s][%d]\n", tmpBuf, iRet);
}
************************************************/

//#include "outlog.h"
#include <string.h>

char * sx_Base64Encode(const unsigned char* aSrc, int *piLen)
{
	static char aDest[1024*100];
	memset(aDest,0x00,sizeof(aDest));
	int iLen = *piLen;
	if((iLen + 2) / 3 * 4 >= sizeof(aDest))
	{
		return NULL;
	}
	int iRet = Base64Encode(aDest,aSrc,iLen);
	if(iRet < 0 || iRet >= sizeof(aDest))
	{
		return NULL;
	}
	return aDest;
}

char * sx_Base64Decode(const char *aSrc,int * piLen)
{
	static char aDest[1024*100];
	memset(aDest,0x00,sizeof(aDest));
	int iLen = *piLen;
	if((iLen + 3) / 4 * 3 >= sizeof(aDest))
	{
		return NULL;
	}
	int iRet = Base64Decode((unsigned char * const)aDest,aSrc);
	if(iRet < 0 || iRet >= sizeof(aDest))
	{
		return NULL;
	}
	return aDest;
}
